#!/bin/bash

# 简化版服务管理脚本 sv.sh
# 用法: ./sv.sh [app|cache|monitor|td] [start|stop|restart|status|test]
# 或者: ./sv.sh [all] [start|stop|restart|status]
# 或者: ./sv.sh update_cache_db local - 更新本地数据库缓存系统
# 或者: ./sv.sh update_cache_db remote - 更新远程服务器数据库缓存系统

# 远程服务器信息
SERVER="root@182.160.6.140"
DEPLOY_PATH="/var/www/binance-analysis"

# 各服务使用的端口
APP_PORT=3000
CACHE_PORT=3001
MONITOR_PORT=3002
TD_MONITOR_PORT=3003

# 检查参数
if [ $# -lt 1 ]; then
  echo "用法: $0 [服务] [命令]"
  echo "服务:"
  echo "  app     - 主应用 (端口: $APP_PORT)"
  echo "  cache   - 缓存服务 (端口: $CACHE_PORT)"
  echo "  monitor - 监控服务 (端口: $MONITOR_PORT)"
  echo "  td      - TD序列监控服务 (端口: $TD_MONITOR_PORT)"
  echo "  all     - 所有服务"
  echo "命令:"
  echo "  start   - 启动服务"
  echo "  stop    - 停止服务"
  echo "  restart - 重启服务(包含代码更新)"
  echo "  status  - 显示服务状态"
  echo "  test    - 执行监控服务测试 (仅monitor和td服务可用)"
  echo ""
  echo "特殊命令:"
  echo "  update_cache_db local  - 更新本地数据库缓存系统"
  echo "  update_cache_db remote - 更新远程服务器数据库缓存系统"
  exit 1
fi

# 处理特殊命令
if [ "$1" == "update_cache_db" ]; then
  if [ "$2" == "local" ]; then
    echo "====== 开始部署本地数据库缓存系统 ======"
    
    # 检查本地数据库连接
    echo "正在检查数据库连接..."
    node scripts/check_db.js
    if [ $? -ne 0 ]; then
      echo "数据库连接失败，请检查配置"
      exit 1
    fi
    
    # 创建缓存相关表和存储过程
    echo "正在创建缓存表和存储过程..."
    mysql -u root -p < scripts/create_cache_table.sql
    if [ $? -ne 0 ]; then
      echo "创建缓存表失败，请检查SQL脚本或数据库权限"
      exit 1
    fi
    echo "缓存表创建成功"
    
    # 重新启动应用
    echo "正在重启应用..."
    ./scripts/restart.sh
    if [ $? -ne 0 ]; then
      echo "应用重启失败，请手动检查"
      exit 1
    fi
    echo "应用重启成功"
    
    # 检查缓存服务是否可用
    echo "正在检查缓存服务..."
    sleep 5
    curl -s http://localhost:3000/api/stats/metrics/cache > /dev/null
    if [ $? -ne 0 ]; then
      echo "警告：缓存服务可能未正常启动，请手动检查"
    else
      echo "缓存服务已正常启动"
    fi
    
    echo "====== 本地数据库缓存系统部署完成 ======"
    echo "可以通过统计页面的缓存管理选项卡查看缓存状态"
    echo "更多信息请参阅docs/CACHE_README.md文档"
    exit 0
  elif [ "$2" == "remote" ]; then
    echo "====== 开始部署远程服务器数据库缓存系统 ======"
    
    # 先上传必要的SQL脚本
    echo "上传缓存表创建脚本到服务器..."
    scp scripts/create_cache_table.sql $SERVER:$DEPLOY_PATH/scripts/
    
    # 连接到远程服务器创建缓存表
    echo "连接到远程服务器创建缓存表..."
    ssh $SERVER "
      cd $DEPLOY_PATH && 
      
      # 检查数据库连接
      echo '正在检查数据库连接...'
      node scripts/check_db.js
      if [ \$? -ne 0 ]; then
        echo '数据库连接失败，请检查配置'
        exit 1
      fi
      
      # 创建缓存表 - 使用已知的数据库连接信息
      echo '正在创建缓存表和存储过程...'
      # 配置数据库连接参数
      DB_USER='root'
      DB_PASS='BinanceRoot2023'
      DB_NAME='binance_klines'
      
      echo \"使用数据库: \$DB_USER@\$DB_NAME\"
      mysql -u\$DB_USER -p\$DB_PASS \$DB_NAME < scripts/create_cache_table.sql
      if [ \$? -ne 0 ]; then
        echo '创建缓存表失败，请检查SQL脚本或数据库权限'
        exit 1
      fi
      echo '缓存表创建成功'
      
      # 重启应用
      echo '正在重启应用...'
      pm2 restart binance-analysis
      if [ \$? -ne 0 ]; then
        echo '应用重启失败，请手动检查'
        exit 1
      fi
      echo '应用重启成功'
      
      # 验证缓存服务
      echo '正在验证缓存服务...'
      sleep 5
      curl -s http://localhost:$APP_PORT/api/stats/metrics/cache > /dev/null
      if [ \$? -ne 0 ]; then
        echo '警告：缓存服务可能未正常启动，请手动检查'
      else
        echo '缓存服务已正常启动'
      fi
    "
    
    echo "====== 远程服务器数据库缓存系统部署完成 ======"
    echo "可以通过统计页面的缓存管理选项卡查看缓存状态"
    echo "更多信息请参阅docs/CACHE_README.md文档"
    exit 0
  else
    echo "错误：update_cache_db命令需要指定目标 (local/remote)"
    echo "用法: $0 update_cache_db [local|remote]"
    exit 1
  fi
fi

SERVICE=$1
ACTION=$2

if [ $# -lt 2 ]; then
  echo "错误：至少需要两个参数"
  exit 1
fi

# 部署代码到服务器的函数
deploy_code() {
  echo "开始更新云服务器代码..."
  
  # 清理旧的打包文件
  rm -f /tmp/deploy.zip
  
  # 打包项目文件(排除node_modules和.git)
  echo "打包项目文件..."
  zip -r /tmp/deploy.zip . -x "node_modules/*" ".git/*" "*.log"
  
  # 上传到服务器
  echo "上传文件到服务器..."
  scp /tmp/deploy.zip $SERVER:$DEPLOY_PATH/
  
  # 清理本地临时文件
  rm /tmp/deploy.zip
  
  # SSH连接到服务器执行更新操作
  echo "连接服务器执行更新..."
  ssh $SERVER "
    cd $DEPLOY_PATH
    
    echo '备份当前node_modules...'
    if [ -d 'node_modules' ]; then
      mv node_modules node_modules_bak
    fi
    
    echo '清理旧文件...'
    find . -maxdepth 1 -not -name 'node_modules_bak' -not -name '.' -not -name '..' -not -name 'deploy.zip' -exec rm -rf {} \;
    
    echo '解压新文件...'
    unzip -o deploy.zip
    rm -f deploy.zip
    
    echo '恢复node_modules...'
    if [ -d 'node_modules_bak' ]; then
      rm -rf node_modules
      mv node_modules_bak node_modules
    fi
    
    echo '更新pm2...'
    npm install pm2@latest -g
    
    echo '安装新依赖...'
    npm install
    
    echo '设置文件权限...'
    if [ -d 'scripts' ]; then
      chmod +x scripts/*.sh
      # 确保TD序列监控脚本权限
      if [ -f 'scripts/start_td_monitor.sh' ]; then
        echo '设置TD序列监控脚本执行权限...'
        chmod +x scripts/start_td_monitor.sh
      fi
    fi
  "
  
  echo "代码更新完成！"
}

# 清理端口并启动应用的函数
clean_port_and_start_app() {
  local PORT=$1
  local APP_NAME=$2
  local SCRIPT_PATH=$3
  
  echo "清理${PORT}端口并启动${APP_NAME}..."
  ssh $SERVER "
    cd $DEPLOY_PATH && 
    
    # 停止旧的应用进程
    pm2 stop ${APP_NAME} || true
    pm2 delete ${APP_NAME} || true
    
    # 查找并杀死可能占用端口的进程
    PORT_PID=\$(lsof -t -i:${PORT}) 
    if [ ! -z \"\$PORT_PID\" ]; then
      echo \"发现进程 \$PORT_PID 占用端口${PORT}，正在终止...\"
      kill -9 \$PORT_PID
      sleep 1
    fi
    
    # 再次检查确保端口已释放
    PORT_PID=\$(lsof -t -i:${PORT})
    if [ ! -z \"\$PORT_PID\" ]; then
      echo \"仍有进程占用${PORT}端口，再次尝试终止...\"
      kill -9 \$PORT_PID
      sleep 2
    fi
    
    # 启动应用，传入环境变量设置端口
    PORT=${PORT} pm2 start ${SCRIPT_PATH} --name ${APP_NAME} && 
    pm2 save
  "
}

# 只重启应用的函数，不清理端口
restart_app() {
  local APP_NAME=$1
  local SCRIPT_PATH=$2
  local PORT=$3
  
  # 先部署代码
  deploy_code
  
  echo "重启${APP_NAME}服务..."
  ssh $SERVER "
    cd $DEPLOY_PATH &&
    
    # 检查应用是否存在
    if pm2 list | grep -q ${APP_NAME}; then
      # 如果应用存在，直接重启
      echo \"应用${APP_NAME}存在，执行重启...\"
      pm2 restart ${APP_NAME} && pm2 save
    else
      # 如果应用不存在，执行完整启动流程
      echo \"应用${APP_NAME}不存在，执行完整启动流程...\"
      PORT=${PORT} pm2 start ${SCRIPT_PATH} --name ${APP_NAME} && pm2 save
    fi
  "
}

# 处理所有服务
handle_all_services() {
  local ACTION=$1
  
  case $ACTION in
    start)
      echo "启动所有服务..."
      clean_port_and_start_app $APP_PORT "binance-analysis" "src/server.js"
      clean_port_and_start_app $CACHE_PORT "cache-updater" "scripts/update_cache.js"
      clean_port_and_start_app $MONITOR_PORT "monitor-app" "scripts/monitor.js"
      clean_port_and_start_app $TD_MONITOR_PORT "td-monitor" "scripts/monitor_td_sequence.js"
      ;;
    restart)
      echo "重启所有服务..."
      # 先部署代码
      deploy_code
      # 然后重启所有服务
      restart_app "binance-analysis" "src/server.js" $APP_PORT
      restart_app "cache-updater" "scripts/update_cache.js" $CACHE_PORT
      restart_app "monitor-app" "scripts/monitor.js" $MONITOR_PORT
      restart_app "td-monitor" "scripts/monitor_td_sequence.js" $TD_MONITOR_PORT
      ;;
    stop)
      echo "停止所有服务..."
      ssh $SERVER "pm2 stop all && pm2 save"
      ;;
    status)
      echo "所有服务状态:"
      ssh $SERVER "pm2 list"
      ;;
    *)
      echo "未知操作: $ACTION"
      exit 1
      ;;
  esac
}

# 根据服务和操作执行相应命令
case $SERVICE in
  app)
    case $ACTION in
      start)
        clean_port_and_start_app $APP_PORT "binance-analysis" "src/server.js"
        ;;
      restart)
        restart_app "binance-analysis" "src/server.js" $APP_PORT
        ;;
      stop)
        ssh $SERVER "pm2 stop binance-analysis && pm2 delete binance-analysis && pm2 save"
        ;;
      status)
        ssh $SERVER "pm2 list | grep binance-analysis"
        ;;
      *)
        echo "未知操作: $ACTION"
        exit 1
        ;;
    esac
    ;;
  cache)
    case $ACTION in
      start)
        clean_port_and_start_app $CACHE_PORT "cache-updater" "scripts/update_cache.js"
        ;;
      restart)
        restart_app "cache-updater" "scripts/update_cache.js" $CACHE_PORT
        ;;
      stop)
        ssh $SERVER "pm2 stop cache-updater && pm2 delete cache-updater && pm2 save"
        ;;
      status)
        ssh $SERVER "pm2 list | grep cache-updater"
        ;;
      *)
        echo "未知操作: $ACTION"
        exit 1
        ;;
    esac
    ;;
  monitor)
    case $ACTION in
      start)
        clean_port_and_start_app $MONITOR_PORT "monitor-app" "scripts/monitor.js"
        ;;
      restart)
        restart_app "monitor-app" "scripts/monitor.js" $MONITOR_PORT
        ;;
      stop)
        ssh $SERVER "pm2 stop monitor-app && pm2 delete monitor-app && pm2 save"
        ;;
      status)
        ssh $SERVER "pm2 list | grep monitor-app"
        ;;
      test)
        echo "执行监控服务测试..."
        ssh $SERVER "cd $DEPLOY_PATH && NODE_ENV=production node scripts/monitor.js test"
        ;;
      *)
        echo "未知操作: $ACTION"
        exit 1
        ;;
    esac
    ;;
  td)
    case $ACTION in
      start)
        clean_port_and_start_app $TD_MONITOR_PORT "td-monitor" "scripts/monitor_td_sequence.js"
        ;;
      restart)
        restart_app "td-monitor" "scripts/monitor_td_sequence.js" $TD_MONITOR_PORT
        ;;
      stop)
        ssh $SERVER "pm2 stop td-monitor && pm2 delete td-monitor && pm2 save"
        ;;
      status)
        ssh $SERVER "pm2 list | grep td-monitor"
        ;;
      test)
        echo "执行TD序列监控服务测试..."
        ssh $SERVER "cd $DEPLOY_PATH && NODE_ENV=production node scripts/monitor_td_sequence.js test"
        ;;
      *)
        echo "未知操作: $ACTION"
        exit 1
        ;;
    esac
    ;;
  all)
    handle_all_services $ACTION
    ;;
  *)
    echo "未知服务: $SERVICE"
    echo "可用服务: app, cache, monitor, td, all"
    exit 1
    ;;
esac

echo "操作完成！" 